Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
2 of 8 Add more examples.

Disclaimer: I've never written a line of code in any of Lisp dialects.

Since OP mentions Lisp quasiquote mechanism, maybe we can implement something similar in Mathematica.

As a basis for quoting mechanism we can use Inactive symbols. Although Inactivate function inactivates only symbols that are heads of expressions, as Leonid mentioned in his answer, we can easily overcome this limitation by manually wrapping all relevant symbols with Inactive.

We start with extracting heads that are ignored by Inactivate and converting them to patterns:

ClearAll[$quoteSymbolExclusions, $quoteExpressionExclusions]
$quoteSymbolExclusions = 
    Alternatives @@
        Cases[Developer`$InactivateExclusions, {sym_, "Symbol"} :> sym];
$quoteExpressionExclusions = 
    Alternatives @@ Prepend[
        Cases[
            Developer`$InactivateExclusions,
                {sym_, "Expression"} :> Blank[sym]
            ],
            _Inactive
        ];

And now quote, quasiquote, unquote and eval functions. quote and quasiquote simply replace all symbols (except excluded ones) by symbols wrapped with Inactive, only difference between them is that the latter doesn't inactivate expressions with head unquote. eval simply strips Inactive wrappers.

ClearAll[quote, quasiquote, unquote, eval]

Options[quote] = Options[quasiquote] =
    {"SymbolExclusions" :> $quoteSymbolExclusions};
AppendTo[Options[quote], "ExpressionExclusions" :> $quoteExpressionExclusions];
AppendTo[Options[quasiquote],
    "ExpressionExclusions" :> Prepend[$quoteExpressionExclusions, _unquote]];

SetAttributes[{quote, quasiquote}, HoldFirst]

(#[expr_, OptionsPattern[]] := Unevaluated[expr] /. {
    excluded : OptionValue["ExpressionExclusions"] :> excluded,
    sym : Except[OptionValue["SymbolExclusions"], _Symbol] :> Inactive[sym]
}) & /@ {quote, quasiquote};

SetAttributes[unquote, SequenceHold]
unquote[expr_] := expr

Options[eval] = {"Head" -> Identity, "Pattern" -> _};
eval[expr_, OptionsPattern[]] :=
    OptionValue["Head"][expr] /.
        HoldPattern[Inactive][x : OptionValue["Pattern"]] :> x

Example of quoted expression, we define function h and variable x to show that their evaluation is properly held:

ClearAll[x, h]
x = 5;
h[x_] := 2 x

quasiquote@{
    1 + 2 + x,
    unquote@{(* this part is unquoted, so it'll be evaluated *)
        3 + 4,
        quasiquote@{(* this part is quoted again so it won't be evaluated *)
            5 + 6,
            unquote[7 + 8] (* and this will evaluate *)
        },
        quote@{(* this won't evaluate *)
            9 + 10,
            (* following will also not evaluate,
               since it's inside quote not quasiquote *)
            unquote[11 + 12]
        }
    },
    # + 1 &[3],
    f[g[x]][h[b]]
}
% // eval
(* {
       1 + 2 + Inactive[x],
       {
           7,
           {5 + 6, 15},
           {9 + 10, unquote[11 + 12]}
       },
       (#1+1&)[3],
       f[g[Inactive[x]]][h[Inactive[b]]]
   } *)
(* {8, {7, {11, 15}, {19, 23}}, 4, f[g[5]][2 b]} *)

Example of generation of code of Module from OP:

ClearAll[a, b, c, d]
a = 1;
b = 2;
inactiveModuleCode =
    quasiquote@Module[
        unquote@MapThread[quote[Set], {quote@{a, b, c, d}, {1, 2, 3, 4}}],
        Print[a, b, c, d]
    ]
eval[%, "Head" -> Hold]
(* Module[{Inactive[a] = 1, Inactive[b] = 2, Inactive[c] = 3, Inactive[d] = 4},
       Print[Inactive[a], Inactive[b], Inactive[c], Inactive[d]]
   ] *)
(* Hold[Module[{a = 1, b = 2, c = 3, d = 4}, Print[a, b, c, d]]] *)

Lookup table example:

symbolMap = quote[
    <|a -> aLookup, b -> bLookup|>,
    "SymbolExclusions" -> Association | Rule
]
quote@If[a > 1, lookupForm[b, 23], lookupForm[a, 24]] /.
    IgnoringInactive@lookupForm[x_, i_] :> quote[Part][symbolMap[x], i]
eval[%, "Head" -> Hold]
(* <|Inactive[a] -> Inactive[aLookup], Inactive[b] -> Inactive[bLookup]|> *)
(* If[Inactive[a] > 1, Inactive[bLookup][[23]], Inactive[aLookup][[24]]] *)
(* Hold[If[a > 1, bLookup[[23]], aLookup[[24]]]] *)

"Quoted" code can be easily manipulated and composed:

inactiveFDef = quasiquote[
    f[x_] :=
        unquote[inactiveModuleCode /. {
            quote[a = _] :> quote[a = x],
            quote[Print][x_, y_, rest__] :> 
                quasiquote@h[
                    unquote[(2 + 5) x],
                    3 10 y,
                    unquote[Sequence @@ {rest}]
                ]
        }
    ]
]
eval[inactiveFDef, "Head" -> Hold]
(* f[Pattern[Inactive[x], _]] :=
       Module[{Inactive[a] = Inactive[x], Inactive[b] = 2, Inactive[c] = 3, Inactive[d] = 4},
           h[7 Inactive[a],3*10*Inactive[b],Inactive[c],Inactive[d]]
       ] *)

and, when necessary, evaluated:

ClearAll[f]
eval[inactiveFDef]
?? f
(* Global`f
   f[x_]:=Module[{a=x,b=2,c=3,d=4},h[7 a,3 10 b,c,d]] *)

f[z]
(* h[7 z, 60, 3, 4] *)