Getting the channel/fields setup
First, I created a new channel/field group for storing my forms. I opened up the docs for FreeForm and proceeded to make a custom field for almost every parameter that exp:freeform:form supports. While you don't need to map out every field, I did so here for the sake of completeness. What you don't need you can always hide via a publish layout.

I purposely left out some of the fields involving parameters dealing with required fields and recipients. Let's look at the two fields that don't map directly to FreeForm parameters: form_recipients and form_fields.
The first field, form_recipients, is a Matrix field that allows you to name up to three recipients and specify their email address. When you use this feature, the recipients emails are hidden from the markup. FreeForm has 4 different parameters to handle recipients, but with a little bit of template logic we can automatically fill out those parameters based on what is entered into this single field.

The next field, form_fields, is what makes the whole thing come together. Thanks to Low's FreeForm field and Matrix, we can create a Matrix field that lets us map our fields to fields specified in Freeform and configure them as needed:

Beyond just the Low FreeForm field, I also have extra columns for field labels, CSS classes, types, whether the field is required, and whether to create a newline after the element (you'll see in the example below).
Setting up the template
Once the channel/fields have been set up, it's time to jump into the template logic. Since I want to be able to reuse my form template, I created a new hidden template called 'site/.form' that I'll use to pull and display my custom form from the EE database. It'll only take one embed variable, form_id, so we know what form we need to pull. You'll see that I'm also using NSM Transplant to handle some of the setup (for required fields and recipients), but you could probably do without it.
First thing to add is our exp:channel:entries tag and the exp:nsm_transplant:body tag:
{exp:channel:entries channel="forms" dynamic="no" entry_id="{embed:form_id}"}
{exp:nsm_transplant:body}
...
{/exp:nsm_transplant:body}
{/exp:channel:entries}
Immediately afterwards, I use NSM Transplant to check whether we're using the recipients field, and if so, cache the recipient's names/emails:
{!-- check if we're using the recipients feature of freeform, if so, set some variables needed for later --}
{if form_recipients}
{exp:nsm_transplant:content id="use_recipients"}yes{/exp:nsm_transplant:content}
{form_recipients}
{exp:nsm_transplant:content id="recipient{row_count}"}{recipient_name}|{recipient_email}{/exp:nsm_transplant:content}
{/form_recipients}
{/if}
Next, we cache the names of the required fields (if any):
{!-- build out our required fields --}
{exp:nsm_transplant:content id="required_fields"}{form_fields backspace="1" search:field_required="y"}{field_field}|{/form_fields}
{/exp:nsm_transplant:content}
With that initial template setup out of the way, we can get on to the heavy lifting:
{!-- begin heavy lifting --}
{exp:freeform:form collection="{form_collection}"
file_upload="{form_file_upload}"
form:id="{form_attribute_id}"
form:name="{form_attribute_name}"
form:class="{form_attribute_class}"
mailinglist="{form_mailing_list}"
mailinglist_opt_in="{form_mailing_list_opt_in}"
notify="{form_notify}"
onsubmit="{form_onsubmit}"
prevent_duplicate_on="{form_prevent_duplicate_on}"
redirect_on_duplicate="{form_redirect_on_duplicate}"
require_ip="{form_require_ip}"
required="{required_fields}"
return="{form_return}"
secure_action="{form_secure_action}"
secure_return="{form_secure_return}"
send_attachment="{form_send_attachment}"
send_user_attachment="{form_send_user_attachment}"
send_user_email="{form_send_user_email}"
status="{form_status}"
template="{form_template}"
user_email_template="{form_user_email_template}"
recipients="{use_recipients}"
recipient1="{recipient1}"
recipient2="{recipient2}"
recipient3="{recipient3}"
recipient_limit="{form_recipient_limit}"
recipient_template="{form_recipient_template}"
parse="inwards"}
{!-- warn if we have required fields --}
{if required_fields}
IMPORTANT: Required fields are marked with an asterisk (*)
{/if}
...
{/exp:freeform:form}
And finally we get to the fields loop, where we loop through each field specified in form_fields and output the right kind of form input based on the type of field chosen in the control panel:
{!-- the actual fields loop --}
{form_fields}
{!-- handle the field types we specified in the channel custom fields --}
{if field_type == "text"}
{if field_label}{field_label}{if field_required}*{/if}{/if}{if field_newline_after}{/if}
{/if}
{if field_type == "textarea"}
{if field_label}{field_label}{if field_required}*{/if}{/if}{if field_newline_after}{/if}
{/if}
{if field_type == "state"}
{if field_label}{field_label}{if field_required}*{/if}{/if}
AL
AK
AZ
...
WY
{if field_newline_after}{/if}
{/if}
{if field_type == "country"}
{if field_label}{field_label}{if field_required}*{/if}{/if}
Afghanistan
Albania
Algeria
...
Zimbabwe
{if field_newline_after}{/if
{/if}
{/form_fields}
{!--now that wasn't so hard, was it? --}
The finished form
Here's an example of a form I built using this method.
Form as configured on the backend:

Form as viewed from the frontend:

While this example is probably too complex for everyday content authors/editors, it can easily be distilled down so that even your least tech savvy client can build their own form. My goal was to build this so that I had full flexibility for this particular project, and so far it's working wonderfully. I hope someone else will find this useful. Comments and feedback appreciated.