Erlang's compiler will do some inlining but it tends to be done at very specific points in time so lambda lifting might be done after the inline passes. I believe the lists module gets inlined most of the time though so I bet a lot of the lambda forms end up with very similar output when compared to hand-rolled recursive calls.
The real overhead comes with allocation of the "closure" state. There isn't much of any optimization to keep this in BEAM registers when the function call isn't inlined... but I might be wrong. It's been awhile since I've compared internal representations between different forms.
If you're curious, I'd be happy to provide some pointers on how to dig into these intermediate forms.
Robert Virding also has some great talks but I can't find the specific one where he discusses some of the lesser known compilation steps. At the end of the day, I learned the most from reading Erlang source code though. There's a lot to see in the Core Erlang compilation code: https://github.com/erlang/otp/tree/maint/lib/compiler/src
As to answer some questions elsewhere in this discussion on why BEAM code isn't targeted directly, it is poorly documented but you also lose out on a lot of these optimizations which happen at the Core Erlang stage. These are all things you'll have to reinvent.
There is debate on whether Core Erlang is a better target than Erlang but I'll skip that debate for now. Some languages, like Elixir target Erlang AST structures rather than Core Erlang while others (LFE) target Core Erlang.