Common lisp's read macros are indeed a different beast. Mutating the bytes pulled from file before parsing them is more powerful than operating on the lists of symbols.
Macros imply a phase separation which fexpr do not. The compile time diagnostics and similar are an artifact of that phase separation, not of evaluation sequencing.
If one wants to build in that phase separation, I think it follows that unhygienic macros are the simple option. Hygienic macros still carry much implementation complexity.
If one wants hygienic behaviour, fexpr do that exactly as easily as lexically scoped lambdas, because they literally are lambda which pass the argument forms unevaluated. I implemented that as a bool tag on the function affecting calling convention - do you map eval across the arguments or not during the function call - and that's sufficient.
If the desired behaviour is variable capture from the calling environment, it takes more effort from a fexpr than from a macro. You write (eval env 'foo) instead of ,foo or similar.
I don't see a particular need for a code walker - in the simple case the argument gets passed around a little then evaluated, in the complicated case you need to walk the arguments the same way a macro would want to.
The phase separation thing I had forgotten about. As in warning messages during compilation so that you have invariants at runtime. Macros fit that model better. Fexpr and compilation are an uneasy combination.