Not an automatic procedure, but not so difficult to use:
\documentclass{article}
\usepackage{tikz}
\usepackage{subfig}
\newcount\bsubfloatcount
\newtoks\bsubfloattoks
\newdimen\bsubfloatht
\makeatletter
\newcommand{\bsubfloat}[2][]{%
\sbox\z@{#2}%
\ifdim\bsubfloatht<\ht\z@
\bsubfloatht=\ht\z@
\fi
\advance\bsubfloatcount\@ne
\@namedef{bsubfloat\romannumeral\bsubfloatcount}{%
\subfloat[#1]{\vbox to\bsubfloatht{\hbox{#2}\vfill}}}%
}
\newcommand{\resetbsubfloat}{\bsubfloatcount\z@\bsubfloatht=\z@}
\makeatother
\begin{document}
\begin{figure}
\centering
\bsubfloat[Small circle]{%
\begin{tikzpicture}
\draw circle (1.25cm) {};
\end{tikzpicture}%
}
\bsubfloat[Big circle]{%
\begin{tikzpicture}
\draw circle (2cm) {};
\end{tikzpicture}%
}
\bsubfloati\qquad\bsubfloatii
\caption{Circles}
\end{figure}
\end{document}
The \bsubfloat commands are just for doing the calculation, then you can use \bsubfloati, \bsubfloatii, \bsubfloatiii, \bsubfloativ and so on (they are reset on each figure environment) to set up the row of subfloats.
If you have multiple rows, you should use \resetbsubfloat between them and use again \bsubfloati and so on for the placement.
More automatic procedure
Here is one, it has some weaknesses, but it should work.
\documentclass{article}
\usepackage{tikz}
\usepackage{subfig}
\newtoks\bsubfloattoks
\newdimen\bsubfloatht
\makeatletter
\newenvironment{bsubfloatrows}[1][\quad]
{\def\bsubfloatspace{#1}\resetbsubfloatrows
\def\\{\printbsubfloatrow\resetbsubfloatrows\par
\@ifnextchar[{\bsubfloatvspace}{}}%
\def\bsubfloatvspace[##1]{\vspace{##1}}%
}
{\printbsubfloatrow}
\newcommand{\bsubfloat}[2][]{%
\sbox\z@{#2}%
\ifdim\bsubfloatht<\ht\z@
\bsubfloatht=\ht\z@
\fi
\bsubfloattoks=\expandafter{\the\bsubfloattoks
\bsubfloatspace\subfloat[#1]{\vbox to\bsubfloatht{\hbox{#2}\vfill}}}%
}
\newcommand\resetbsubfloatrows{\bsubfloatht\z@\bsubfloattoks={\@gobble}}
\newcommand{\printbsubfloatrow}{\the\bsubfloattoks}
\makeatother
\begin{document}
\begin{figure}
\centering
\begin{bsubfloatrows}[\hfill]
\bsubfloat[Small circle]{%
\begin{tikzpicture}
\draw circle (1.25cm) {};
\end{tikzpicture}%
}
\bsubfloat[Big circle]{%
\begin{tikzpicture}
\draw circle (2cm) {};
\end{tikzpicture}%
}
\\[36pt]
\bsubfloat[Small circle]{%
\begin{tikzpicture}
\draw circle (1cm) {};
\end{tikzpicture}%
}
\bsubfloat[Big circle]{%
\begin{tikzpicture}
\draw circle (1.2cm) {};
\end{tikzpicture}%
}
\end{bsubfloatrows}
\caption{Circles}
\end{figure}
\end{document}
As you see, subfloats are enclosed in an environment, where each row is processed separately as regards the height. The horizontal spacing between two subfloats is given as optional argument to the environment (that's one weakness).