Well I've looked at this a bit and honestly there is no great solution, its a bit of the limitation of the regex.
I explored adding a look behind to catch the trailing ) (and others symmetric issues) but aside from getting a bit ugly, I was concerned with having the look ahead and look behind for this, we could end up in a exhaustive recursion situation.
So the solutions as I see them are:
1) Don't allow url's with )'s in them. This is not the worst things since the autolinker is a "goodie" .. it will miss valid links which is what the url bbc is for anyway.
2) Pull that regex out of the current preg_replace array and add it to a separate preg_replace_callback where we can see if it starts with a ( and if so trim any trailing one. Something like
if (is_string($result = preg_replace_callback('~(?<=([\s>\.(;\'"])|^)((?:http|https)://[\w\-_%@:|]+(?:\.[\w\-_%]+)*(?::\d+)?(?:/[\p{L}\w\-_\~%\.@!,\?&;=#(){}+:\'\\\\]*)*[/\w\-_\~%@\?;=#}\\\\]?)~ui', create_function('$m', 'return $m[1] !== "(" ? "[url]$m[2][/url]" : "[url]" . rtrim("$m[2]", ")") . "[/url])";'), $data)));
$data = $result;
That covers the most used case and still allows links with )'s in them, even trailing ones
So 1) is easy and cheap, 2) is more correct for this instance but a tad more expensive (probably not in real use) in terms of processing.