Change your method signature to return the interface rather than instance of SomeObject class. You can do that in type library editor like this:

The generated code would then be:
function THelper.CreateSomeObject: ISomeObject;
begin
end;
Edit 1
As per comment: Although you've provided a lot of text in your question, it still lacks some essential information. You've mentioned some pointer operations, but that isn't something that you are supposed to deal with in a typical scenario when developing a COM server.
So I tried to re-create your scenario myself in Delphi 7 (oldest delphi version that I have installed). I created a COM server (ActiveX Library project in Delphi) similar to the one above. My implementation of method CreateSomeObject was:
function THelper.CreateSomeObject: ISomeObject;
begin
Result := TSomeObject.Create;
end;
Implementation of method TSomeObject.HelloWorld is unimportant. Then I registered the server via IDE function Run > Register ActiveX Server. After that I created sample console application in Delphi, imported type library (Project > Import Type Library) and added few lines of code to main program:
uses
ActiveX, COMTest_TLB;
var
_Helper: IHelper;
_SomeObject: ISomeObject;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
_Helper := CoHelper.Create;
_SomeObject := _Helper.CreateSomeObject;
_SomeObject.HelloWorld;
end.
The console application ran to completion without a crash or unexpected result. So far so good. Then I created sample C#.NET console application (.NET 4.5.2) with reference to my COMTest library:
using System;
using COMTest;
class Program
{
[STAThread]
static void Main(string[] args)
{
var helper = new Helper();
var someObject = helper.CreateSomeObject();
someObject.HelloWorld();
}
}
And indeed the application was crashing with AccessViolationException. I quickly set up debugging of COM server by setting host application to .NET console application and enabling remote debug symbols in project's linker options (I'm sure you've figured that out already). Creation of TSomeObject instance went smoothly, but the assignment to Result failed.
There's some compiler magic when assigning value to a variable of managed type (interface in this case). It starts with clearing the destination which basically is a call to _Release, if the destination is not nil. And to my surprise in case of .NET console app client it wasn't! So I amended the implementation to:
function THelper.CreateSomeObject: ISomeObject;
begin
Pointer(Result) := nil;
Result := TSomeObject.Create;
end;
Clearing the result before its first usage as interface did the trick. I haven't dug into detail on why that happens, but I will certainly do. I'll also check it with newer Delphi version and publish my findings in another edit of this answer.
Here you can find some great resources related to COM development in Delphi.
http://www.techvanguards.com/com/
Disclaimer: I'm not related to that site in any way, I just find it incredibly useful.
Edit 2
COM interface methods should return HRESULT by convention. That's the default mechanism in COM to report errors. Returning additional value(s) from a method should be implemented via parameters with [Out] modifier. Alternatively a parameter can be marked with [Out, RetVal] modifier (usually the last one) to indicate the return value of the method. Note that [Out] parameters are passed by reference, which you must indicate with additional asterisk (*) symbol appended to type name in type library editor. So ISomeObject* becomes [Out] ISomeObject**.
Delphi supports safecall calling convention and thus it can eliminate HRESULT return value from your method signature by wrapping any uncaught exception in your method and passing it back in EAX register allowing the [Out, RetVal] parameter to become the return value. But this is only supported for dual interfaces (see Flags tab of an interface) that are derived from IDispatch. To avoid implementing IDispatch methods you can convert your lightweight COM object to automation object (TAutoObject), if you haven't done that already. This can be achieved by selecting 'Automation Object' option instead of 'COM Object' when adding new item to your ActiveX library.
So this is how the method definition looks like when converted to safecall:

And here's generated code with trivial implementation:
type
THelper = class(TAutoObject, IHelper)
protected
function CreateSomeObject: ISomeObject; safecall;
end;
function THelper.CreateSomeObject: ISomeObject;
begin
Result := TSomeObject.Create;
end;